package com.zy.generate;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;

import java.io.*;
import java.util.*;

/**
 * @Auther: wangyanwei
 * @Date: 2019/9/10 08:35
 * @Description: 代码生成器
 */
public class CodeGenerateApplication {


    /**
     * 功能描述: 获取数据源配置信息
     *
     * @auther: wangyanwei
     * @date: 2019/9/11 14:01
     * @param:
     * @return:
     */
    private static DataSourceConfig getDataSourceConfig() {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/platform?useUnicode=true&useSSL=false&characterEncoding=utf8");
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        return dsc;
    }


    public static void main(String[] args) {

        AutoGenerator mpg = new AutoGenerator();   // 代码生成器
        GlobalConfig gc = new GlobalConfig();     // 全局配置
        String projectPath = System.getProperty("user.dir");    //项目所在目录
        /** 数据源配置 **/
        mpg.setDataSource(getDataSourceConfig());
        /**输入表名**/
        String prefix = scanner("模块名");
        String[] tableName = scanner("表名，多个英文逗号分割").split(",");

        /** 生成entity,dto,vo,controller, service,serviceImpl,mapper,xml **/
        generateCode(gc, mpg, projectPath, tableName,prefix);

    }


    /**
     * 功能描述: 生成 controller,service,serviceImpl,mapper,xml ，再次生成不覆盖之前存在的代码
     *
     * @auther: wangyanwei
     * @date: 2019/9/11 16:14
     * @param:
     * @return:
     */
    private static void generateCode(GlobalConfig gc, AutoGenerator mpg, String projectPath, String[] tableName,String prefix) {

        String moduleName = "platform-web";
        String moduleNameBase = "platform-base";

        gc.setOutputDir(projectPath + "/" + moduleName + "/src/main/java");
        gc.setAuthor("王彦委");
        gc.setOpen(false);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true); // 实体属性 Swagger2 注解
        mpg.setGlobalConfig(gc);

        //包配置
        PackageConfig pc = new PackageConfig();
        String parentPackage = "com.zy.yun";
        pc.setMapper("provider.dao");
        pc.setController("controller." + prefix);
        pc.setService("provider.service");
        pc.setServiceImpl("provider.service.impl");
        pc.setParent(parentPackage);
        pc.setEntity("base.entity");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出（xml文件输出路径）
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！ + pc.getModuleName()
                return projectPath + "/" + moduleName + "/src/main/resources/mapper/"
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }

        });

        //实体类po
        templatePath = "/templates/entity.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + "/platform-base/src/main/java/com/zy/yun/base/entity";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getEntityName());

                File file = new File(entityFile);
                if (file.exists()) {
                    file.delete();
                }

                return entityFile;
            }
        });

        //实体类 dto
        templatePath = "/templates/dto.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + "/platform-base/src/main/java/com/zy/yun/base/entity/dto";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getEntityName()+"DTO");
                return entityFile;
            }
        });

        //实体类 vo
        templatePath = "/templates/vo.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + "/platform-base/src/main/java/com/zy/yun/base/entity/vo";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getEntityName()+"VO");
                return entityFile;
            }
        });

        //控制层
        templatePath = "/templates/controller.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + "/" + moduleName +  "/src/main/java/com/zy/yun/controller/"+prefix;
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getControllerName());
                return entityFile;
            }
        });


        //业务层
        templatePath = "/templates/service.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand =projectPath + "/" + moduleName +  "/src/main/java/com/zy/yun/provider/service";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getServiceName());
                return entityFile;
            }
        });
        templatePath = "/templates/serviceImpl.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + "/" + moduleName +  "/src/main/java/com/zy/yun/provider/service/impl";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getServiceImplName());
                return entityFile;
            }
        });



        //数据层
        templatePath = "/templates/mapper.java.ftl";
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 + pc.getModuleName()
                String expand = projectPath + "/" + moduleName +  "/src/main/java/com/zy/yun/provider/dao";
                String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getMapperName());
                return entityFile;
            }
        });



        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setEntity(null);//取消默认输出
        templateConfig.setXml(null);
        templateConfig.setMapper(null);
        templateConfig.setController(null);
        templateConfig.setService(null);
        templateConfig.setServiceImpl(null);
        mpg.setTemplate(templateConfig);


        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setRestControllerStyle(true);

        // 公共父类
        strategy.setSuperControllerClass("com.zy.yun.controller.common.BaseController");
        // 写于父类中的公共字段
        strategy.setSuperEntityColumns("id");
        strategy.setInclude(tableName);
        strategy.setControllerMappingHyphenStyle(true);
//        strategy.setTablePrefix(pc.getModuleName() + "_");
        strategy.setTablePrefix(prefix + "_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();

    }


    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    private static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "！");
    }




    /**
     * 除去下划线，并首字母大写
     *
     * @param str
     * @return
     */
    public static String replaceUnderLineAndUpperCase(String str) {
        StringBuffer sb = new StringBuffer();
        sb.append(str);
        int count = sb.indexOf("_");
        while (count != 0) {
            int num = sb.indexOf("_", count);
            count = num + 1;
            if (num != -1) {
                char ss = sb.charAt(count);
                char ia = (char) (ss - 32);
                sb.replace(count, count + 1, ia + "");
            }
        }
        String result = sb.toString().replaceAll("_", "");
        return StringUtils.capitalize(result);
    }
    /**
     * 构造类名，除去第一个下划及其前面的字母
     *
     * @param tableName
     * @return
     */
    public static String getClassName(String tableName) {
        if (tableName.indexOf("_") < 0) {
            return replaceUnderLineAndUpperCase(tableName);
        }
        String str = tableName.substring(tableName.indexOf("_") + 1);
        return replaceUnderLineAndUpperCase(str);
    }




    //首字母转小写
    public static String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0))){
            return s;
        }
        else{
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }
    //首字母转大写
    public static String toUpperCaseFirstOne(String s){
        if(Character.isUpperCase(s.charAt(0))){

            return s;
        }
        else{

            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }


}
